/*
 * Copyright 2011 Fabian Wenzelmann
 * 
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 * 
 * Recognition-Procedures-for-Boolean-Functions is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.wenzelmf.booleanFunction.lpb.combinatorial.occurrencePattern;

import java.util.Iterator;
import java.util.SortedMap;

/**
 * A implementation of EntryOccurrencePattern that just uses a sorted map to store the occurrences.
 * 
 * It defines a abstract method to create an empty sorted set.
 * 
 * @author Fabian Wenzelmann
 * @version 1.0
 *
 */
public abstract class SortedMapOccurrencePattern extends EntryOccurrencePattern
{
	private static final long serialVersionUID = -6587723153270377282L;
	
	/*
	 * Stores the entries. Maps size to the occurrence pattern with the size.
	 */
	private SortedMap<Integer, OccurrencePatternEntry> occurrenceMap;
	
	/**
	 * Construct a new SortedMapOccurrencePattern.
	 * 
	 * @param variable The name of the variable the occurrence pattern is created for (identifier of the variable).
	 */
	public SortedMapOccurrencePattern(String variable)
	{
		super(variable);
		this.occurrenceMap = getEmptyMap();
	}
	
	/**
	 * Construct a new SortedMapOccurrencePattern given an initial size.
	 * 
	 * @param variable The name of the variable the occurrence pattern is created for (identifier of the variable).
	 * @param size The initial size of the map (slots).
	 */
	public SortedMapOccurrencePattern(String variable, int size)
	{
		super(variable);
		this.occurrenceMap = getEmptyMap(size);
	}

	/**
	 * Behaves as defines in {@link EntryOccurrencePattern}.
	 * 
	 * prohibits element removal by throwing an UnsupportedOperationException when the {@code remove}
	 * method is called.
	 * 
	 * @return {@inheritDoc}
	 */
	@Override
	public Iterator<OccurrencePatternEntry> entryIterator()
	{
		return new Iterator<OccurrencePatternEntry>()
		{
			Iterator<OccurrencePatternEntry> entries = occurrenceMap.values().iterator();
			@Override
			public boolean hasNext()
			{
				return entries.hasNext();
			}

			@Override
			public OccurrencePatternEntry next()
			{
				return entries.next();
			}

			@Override
			public void remove()
			{
				throw new UnsupportedOperationException("Removing elements from the Occurrence Pattern is not allowed");
			}
			
		};
	}

	@Override
	public int addOccurrence(int variableCount)
	{
		OccurrencePatternEntry entry = occurrenceMap.get(variableCount);
		if(entry == null)
		{
			entry = new OccurrencePatternEntry(variableCount);
			occurrenceMap.put(variableCount, entry);
		}
		return entry.increaseOccurrence();
	}
	
	/**
	 * Create a new sorted map.
	 * 
	 * @return A new, empty sorted map.
	 */
	protected abstract SortedMap<Integer, OccurrencePatternEntry> getEmptyMap();
	
	/**
	 * Create new sorted map given an initial size - the default implementation just calls {@link #getEmptyMap()}.
	 * 
	 * @param initialSize The initial size of the map (slots).
	 * 
	 * @return A new, empty sorted map taking the initial size in account.
	 */
	protected SortedMap<Integer, OccurrencePatternEntry> getEmptyMap(int initialSize)
	{
		return getEmptyMap();
	}
	
}
